---
title: 'Astro DB'
description: 了解如何使用 Astro DB——一个专门为 Astro 设计的全托管 SQL 数据库。
githubIntegrationURL: 'https://github.com/withastro/astro/tree/main/packages/db/'
i18nReady: true
---
import { FileTree } from '@astrojs/starlight/components';
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';
import ReadMore from '~/components/ReadMore.astro';
import Since from '~/components/Since.astro';
import { Steps } from '@astrojs/starlight/components';

Astro DB 是一款专为 Astro 设计的全托管 SQL 数据库。在 Astro 中进行本地开发并部署到任何与 libSQL 兼容的数据库。

Astro DB 是一种配置、开发和查询数据的完整解决方案。每当你运行`astro dev`时，都会在`.astro/content.db`中创建一个本地数据库来管理数据，而无需 Docker 或网络连接。

## 安装

使用内置的 `astro add` 命令安装 [`@astrojs/db` 集成](/zh-cn/guides/integrations-guide/db/)：

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npx astro add db
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro add db
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro add db
  ```
  </Fragment>
</PackageManagerTabs>

## 定义你的数据库

使用 `astro add` 命令安装 `@astrojs/db` 将自动在你的项目中创建一个 `db/config.ts` 文件，你可以在其中定义你的数据库表：

```ts title="db/config.ts"
import { defineDb } from 'astro:db';

export default defineDb({
  tables: { },
})
```

### 表

Astro DB 中的数据是通过 SQL 表存储的。表将你的数据结构化为行和列，其中列强制每行值的类型。

通过提供现有 libSQL 数据库中的数据结构或将在新数据库中收集的数据，在 `db/config.ts` 文件中定义表。这将允许 Astro 为你的项目生成一个 TypeScript 接口来查询该表。这意味着当你访问数据时，将获得完整的 TypeScript 支持，包括属性自动完成和类型检查。

要配置数据库表，应从 `astro:db` 导入并使用 `defineTable()` 和 `column` 工具。然后，为表定义一个名称（区分大小写）以及每列的数据类型。

这个例子配置了一个 `Comment` 表，它有 `author` 和 `body` 的必需文本列。然后，通过 `defineDb()` 导出使其在你的项目中可用。

```ts title="db/config.ts" "Comment"
import { defineDb, defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    author: column.text(),
    body: column.text(),
  }
})

export default defineDb({
  tables: { Comment },
})
```

<ReadMore>查看 [表配置参考](/zh-cn/guides/integrations-guide/db/#表配置参考) 以获取完整的表选项参考。</ReadMore>

### 列

Astro DB 支持以下列类型：

```ts title="db/config.ts" "column.text()" "column.number()" "column.boolean()" "column.date()" "column.json()"
import { defineTable, column } from 'astro:db';

const Comment = defineTable({
  columns: {
    // 文本字符串。
    author: column.text(),
    // 整数值。
    likes: column.number(),
    // 布尔值。
    flagged: column.boolean(),
    // 作为 JavaScript Date 对象查询的日期/时间值。
    published: column.date(),
    // 未经类型化的 JSON 对象。
    metadata: column.json(),
  }
});
```

<ReadMore>查看[表的列参考](/zh-cn/guides/integrations-guide/db/#表配置参考)以获取更多细节。</ReadMore>

### 表引用

表之间的关系是数据库设计中的常见架构。例如，一个 `Blog` 表可能与 `Comment`、`Author` 和 `Category` 等其他几个表密切相关。

你可以使用**引用列**定义来这些表之间的关系并将它们保存到你的数据库中。要建立关系，你需要：

- 在被引用的表上有一个**标识符列**。这通常是带有 `primaryKey` 属性的 `id` 列。
- 在基础表上有一个用于**存储被引用 `id`** 的列。这将使用 `references` 属性来建立关系。

这个例子显示了一个 `Comment` 表的 `authorId` 列引用了 `Author` 表的 `id` 列。

```ts title="db/config.ts" {3, 10}
const Author = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    name: column.text(),
  }
});

const Comment = defineTable({
  columns: {
    authorId: column.number({ references: () => Author.columns.id }),
    body: column.text(),
  }
});
```

## 为你的开发数据库填充数据

在开发过程中，Astro 将使用你的 DB 配置并根据你的架构生成本地类型。这些内容将在每次启动开发服务器时从你的 seed 文件重新生成，并允许你使用类型安全和自动补全来查询和处理你的数据样例。

你将无法在开发过程中访问生产数据，除非你在开发过程中 [连接到远程数据库](#连接到远程数据库)。这样可以保护你的数据，同时允许你使用类型安全的工作数据库进行测试和开发。

要为你的 Astro 项目填充开发数据进行测试和调试，你需要创建一个 `db/seed.ts` 文件。导入 `db` 对象和 `astro:db` 中定义的表。`insert`一些初始数据到每一个表中。这些开发数据应该与数据库模式和生产数据的结构相匹配。

以下例子为 `Comment` 表和 `Author` 表定义了两行开发数据：

```ts title="db/seed.ts"
import { db, Comment, Author } from 'astro:db';

export default async function() {
  await db.insert(Author).values([
    { id: 1, name: "Kasim" },
    { id: 2, name: "Mina" },
  ]);

  await db.insert(Comment).values([
    { authorId: 1, body: 'Hope you like Astro DB!' },
    { authorId: 2, body: 'Enjoy!'},
  ])
}
```

你的开发服务器将在此文件更改时自动重启你的数据库，并每次重新生成类型并从 `seed.ts` 填充新的开发数据。

## 连接一个 libSQL 数据库用于生产

Astro DB 可以连接到任何本地 libSQL 数据库或任何暴露 libSQL 远程协议的托管或自托管服务器。

要连接 Astro DB 到 libSQL 数据库，设置以下从你的数据库提供商获取的环境变量：

- `ASTRO_DB_REMOTE_URL`：连接到本地或远程 libSQL DB 的位置的连接 URL。这可能包括 [URL 配置选项](#远程-url-配置选项) 如 sync 和 encryption 作为参数。
- `ASTRO_DB_APP_TOKEN`：你的 libSQL 服务器的认证 token。这对远程数据库是必须的，对 [本地 DB 如 文件或内存](#url-scheme-和-host) 数据库不是必须的。

根据你的服务，你可能会访问到一个 CLI 或 web UI 来获取这些值。以下部分将演示连接到 Turso 并设置这些值，但你也可以使用任何提供商。

### 开始使用 Turso

Turso 是 [libSQL](https://github.com/tursodatabase/libsql) 背后的公司，libSQL 是 Astro DB 的底层数据库。他们提供了一个完全托管的 libSQL 数据库平台，并与 Astro 完全兼容。

以下步骤将引导你完成安装 Turso CLI、登录（或注册）、创建一个新数据库、获取所需的认证环境变量，并将模式推送到远程数据库的过程。

<Steps>

1. 安装 [Turso CLI](https://docs.turso.tech/cli/installation)。

2. [登录或注册](https://docs.turso.tech/cli/authentication) Turso。

3. 创建一个新数据库。在这个例子中，数据库名称为 `andromeda`。

   ```sh "andromeda"
   turso db create andromeda
   ```

4. 运行 `show` 命令查看新创建数据库的信息：

   ```sh "andromeda"
   turso db show andromeda
   ```

   复制 `URL` 值并将其设置为 `ASTRO_DB_REMOTE_URL` 的值。
   

   ```dotenv title=".env" "libsql://andromeda-houston.turso.io"
   ASTRO_DB_REMOTE_URL=libsql://andromeda-houston.turso.io
   ```

5. 创建一个新 token 认证请求到数据库：

   ```sh "andromeda"
   turso db tokens create andromeda
   ```

   复制命令的输出并将其设置为 `ASTRO_DB_APP_TOKEN` 的值。

   ```dotenv title=".env" add={2} "eyJhbGciOiJF...3ahJpTkKDw"
   ASTRO_DB_REMOTE_URL=libsql://andromeda-houston.turso.io
   ASTRO_DB_APP_TOKEN=eyJhbGciOiJF...3ahJpTkKDw
   ```

6. 将你的 DB schema 和 metadata 推送到新的 Turso 数据库。

   ```sh
   astro db push --remote
   ```

7. 恭喜，现在你已经连接了一个数据库！给自己一个奖励。 👾

   ```sh
   turso relax
   ```

</Steps>

要探索更多 Turso 的功能，请查看 [Turso 文档](https://docs.turso.tech)。

### 连接到远程数据库

Astro DB 允许你连接到本地和远程数据库。默认情况下，Astro 使用一个本地数据库文件用于 `dev` 和 `build` 命令，每次重新创建表并插入开发 seed 数据。

要连接到一个托管的远程数据库，使用 `--remote` 标志。这个标志允许你访问远程数据库，允许你 [接受和持久化用户数据](#插入) 在生产环境中。

配置你的 build 命令使用 `--remote` 标志：

```json title="package.json" "--remote"
{
  "scripts": {
    "build": "astro build --remote"
  }
}
```

你也可以直接在命令行中使用该标志：

```bash
# 使用远程连接构建
astro build --remote

# 使用远程连接开发
astro dev --remote
```

:::caution
在开发过程中使用 `--remote` 时请小心。这会连接到你的生产数据库，所有更改（插入、更新、删除）都会被持久化。
:::

`--remote` 标志在本地构建期间和服务器上都使用远程数据库连接。确保在本地开发环境和部署平台中都设置了必要的环境变量。此外，你可能还需要为非 Node.js 运行时（如 Cloudflare Workers 或 Deno）[配置 web 模式](/zh-cn/guides/integrations-guide/db/#mode)。

当你部署你的 Astro DB 项目时，确保你的部署平台的 build 命令设置为 `npm run build`（或你包管理器的等效命令）以使用在 `package.json` 中配置的 `--remote` 标志。

### 远程 URL 配置选项

`ASTRO_DB_REMOTE_URL` 环境变量配置了数据库的位置以及同步和加密等其他选项。

#### URL scheme 和 host

libSQL 支持 HTTP 和 WebSockets 作为远程服务器的传输协议。它还支持使用本地文件或内存数据库。可以使用以下 URL 方案在连接 URL 中进行配置：

- `memory:` 将使用内存数据库。在这种情况下，主机必须为空。
- `file:` 将使用本地文件。主机是文件的路径 (`file:path/to/file.db`).
- `libsql:` 将通过 libSQL 库首选的协议使用远程服务器（这可能因版本而异）。主机是服务器的地址 (`libsql://your.server.io`).
- `http:` 通过 HTTP 使用远程服务器。`https:` 可以用来启用安全连接。主机与 `libsql:` 相同。
- `ws:` 通过 WebSockets 使用远程服务器。`wss:` 可以用来启用安全连接。主机与 `libsql:` 相同。

libSQL 连接的详细信息（例如加密密钥、复制、同步间隔）可以在远程连接 URL 中作为查询参数进行配置。

例如，要将一个加密的本地文件设置为 libSQL 服务器的嵌入式副本，可以设置以下环境变量：

```dotenv title=".env"
ASTRO_DB_REMOTE_URL=file://local-copy.db?encryptionKey=your-encryption-key&syncInterval=60&syncUrl=libsql%3A%2F%2Fyour.server.io
ASTRO_DB_APP_TOKEN=token-to-your-remote-url
```

:::caution
使用数据库文件是一个高级特性，在部署时应该小心，以防止覆盖你的数据库并丢失你的生产数据。

此外，这种方法在无服务器部署中将无法工作，因为这些环境中没有持久化的文件系统。
:::

#### `encryptionKey`

libSQL 对加密数据库有原生支持。传递这个搜索参数将使用给定的密钥启用加密：

```dotenv title=".env"
ASTRO_DB_REMOTE_URL=file:path/to/file.db?encryptionKey=your-encryption-key
```

#### `syncUrl`

嵌入式副本是 libSQL 客户端的一个特性，它会在本地文件或内存中创建一个完整同步的副本，以实现超快的读取。写入发送到在 `syncUrl` 上定义的远程数据库，并与本地副本同步。

使用此属性传递一个单独的连接 URL 将数据库转换为另一个数据库的嵌入式副本。这应该仅与 `file:` 和 `memory:` 方案一起使用。该参数必须进行 URL 编码。

例如，要将一个数据库设置为 `libsql://your.server.io` 的内存嵌入式副本，可以设置连接 URL 如下：

```dotenv title=".env"
ASTRO_DB_REMOTE_URL=memory:?syncUrl=libsql%3A%2F%2Fyour.server.io
```

#### `syncInterval`

嵌入式副本之间同步的间隔时间，单位为秒。默认情况下，它仅在启动时和写入后同步。

此属性仅在设置 `syncUrl` 时使用。例如，要将内存嵌入式副本设置为每分钟同步，请设置以下环境变量：

```dotenv title=".env"
ASTRO_DB_REMOTE_URL=memory:?syncUrl=libsql%3A%2F%2Fyour.server.io&syncInterval=60
```

## 查询你的数据库

你可以从项目中的任何 [Astro 页面](/zh-cn/basics/astro-pages/#astro-页面)，[端点](/zh-cn/guides/endpoints/) 或 [action](/zh-cn/guides/actions/) 使用提供的 `db` ORM 和查询构建器来查询你的数据库。

### Drizzle ORM

```ts
import { db } from 'astro:db';
```

Astro DB 包含一个内置的 [Drizzle ORM](https://orm.drizzle.team/) 客户端。使用该客户端无需设置或手动配置。当你运行 Astro 时，Astro DB 的 `db` 客户端会自动配置以与你的数据库（本地或远程）进行通信。它使用你明确的数据库架构定义进行类型安全的 SQL 查询，当你引用不存在的列或表时，会出现 TypeScript 错误。

### 查询

以下例子选择了 `Comment` 表的所有行。这将返回来自 `db/seed.ts` 全量的填充的开发数据数组，然后可以在你的页面模板中使用它们：

```astro title="src/pages/index.astro"
---
import { db, Comment } from 'astro:db';

const comments = await db.select().from(Comment);
---

<h2>Comments</h2>

{
  comments.map(({ author, body }) => (
    <article>
      <p>Author: {author}</p>
      <p>{body}</p>
    </article>
  ))
}
```

<ReadMore>查看 [Drizzle `select()` API 参考](https://orm.drizzle.team/docs/select) 以获取完整概述。</ReadMore>

### 插入

要接受用户输入，如处理表单请求并将数据插入到你的远程托管数据库，需要为你的 Astro 项目配置 [按需渲染](/zh-cn/guides/on-demand-rendering/) 并为你的部署环境 [添加一个适配器](/zh-cn/guides/on-demand-rendering/#添加适配器)。

这个例子基于解析后表单的 POST 请求向 `Comment` 表插入一行：

```astro
---
// src/pages/index.astro
import { db, Comment } from 'astro:db';

if (Astro.request.method === 'POST') {
  // 解析表单数据
  const formData = await Astro.request.formData();
  const author = formData.get('author');
  const body = formData.get('body');
  if (typeof author === 'string' && typeof body === 'string') {
    // 将表单数据插入到 Comment 表中
    await db.insert(Comment).values({ author, body });
  }
}

// 在每次请求上渲染新的评论列表
const comments = await db.select().from(Comment);
---

<form method="POST" style="display: grid">
	<label for="author">Author</label>
	<input id="author" name="author" />

	<label for="body">Content</label>
	<textarea id="body" name="body"></textarea>

	<button type="submit">Submit</button>
</form>

<!--渲染 `comments`-->
```

你也可以使用 [Astro actions](/zh-cn/guides/actions/) 向 Astro DB 表中插入数据。以下例子使用一个 action 向 `Comment` 表中插入一行：

```ts
// src/actions/index.ts
import { db, Comment } from 'astro:db';
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
  addComment: defineAction({
    // Actions 用 Zod 保证类型安全，不需要再
    // 在页面中检查 typeof {value} === 'string'
    input: z.object({
      author: z.string(),
      body: z.string(),
    }),
    handler: async (input) => {
      const updatedComments = await db
        .insert(Comment)
        .values(input)
        .returning(); // 返回更新后的评论
      return updatedComments;
    },
  }),
};
```

<ReadMore>

查看 [Drizzle `insert()` API 参考](https://orm.drizzle.team/docs/insert) 以获取完整概述。

</ReadMore>

### 删除

你也可以从 API 端点查询你的数据库。这个例子通过 `id` 参数删除 `Comment` 表中的一行：

```ts
// src/pages/api/comments/[id].ts
import type { APIRoute } from "astro";
import { db, Comment, eq } from 'astro:db';
export const DELETE: APIRoute = async (ctx) => {
  await db.delete(Comment).where(eq(Comment.id, ctx.params.id ));
  return new Response(null, { status: 204 });
}
```

<ReadMore>
查看 [Drizzle `delete()` API 参考](https://orm.drizzle.team/docs/delete) 以获取完整概述。
</ReadMore>

### 过滤

要通过特定属性查询表结果，请使用 [Drizzle 的部分查询选项](https://orm.drizzle.team/docs/select#partial-select)。例如，向你的 `select()` 查询添加 [一个 `.where()` 调用](https://orm.drizzle.team/docs/select#filtering)，并传递你想做的比较操作。

以下例子查询了 `Comment` 表中包含 "Astro DB" 短语的所有行。使用 [`like()` 操作符](https://orm.drizzle.team/docs/operators#like) 检查 `body` 中是否存在短语：

```astro title="src/pages/index.astro"
---
import { db, Comment, like } from 'astro:db';

const comments = await db.select().from(Comment).where(
    like(Comment.body, '%Astro DB%')
);
---
```

### Drizzle 辅助工具

所有用于构建查询的 Drizzle 辅助工具都从 `astro:db` 模块中暴露出来。这包括：

- [过滤操作符](https://orm.drizzle.team/docs/operators) 如 `eq()` 和 `gt()`
- [聚合辅助工具](https://orm.drizzle.team/docs/select#aggregations-helpers) 如 `count()`
- 用于编写原始 SQL 查询语句的 [`sql` 辅助工具](https://orm.drizzle.team/docs/sql)

```ts
import { eq, gt, count, sql } from 'astro:db';
```

### 关系

你可以使用 SQL 连接从多个表查询关联的数据。要创建一个连接查询，请使用连接操作符扩展你的 `db.select()` 语句。每个函数都接受一个要连接的表和一个条件来匹配两个表之间的行。

这个例子使用了 `innerJoin()` 函数将 `Comment` 的作者与他们相关的 `Author` 信息连接起来，基于 `authorId` 列。这将返回一个对象数组，每个 `Author` 和 `Comment` 行作为顶级属性：

```astro title="src/pages/index.astro"
---
import { db, eq, Comment, Author } from 'astro:db';

const comments = await db.select()
  .from(Comment)
  .innerJoin(Author, eq(Comment.authorId, Author.id));
---

<h2>Comments</h2>

{
  comments.map(({ Author, Comment }) => (
    <article>
      <p>Author: {Author.name}</p>
      <p>{Comment.body}</p>
    </article>
  ))
}
```

<ReadMore>

查看 [Drizzle 连接参考](https://orm.drizzle.team/docs/joins#join-types) 以获取所有可用的连接操作符和配置选项。

</ReadMore>

### 批处理事务

所有远程数据库查询都作为网络请求进行。当进行大量查询，或者如果任何查询失败需要自动回滚时，你可能需要将查询批量处理为单个事务。

这个例子使用 `db.batch()` 方法在单个请求中填充多行：

```ts
// db/seed.ts
import { db, Author, Comment } from 'astro:db';

export default async function () {
  const queries = [];
  // 使用单个网络请求将 100 个样本数据填充到你的远程数据库中。
  for (let i = 0; i < 100; i++) {
    queries.push(db.insert(Comment).values({ body: `Test comment ${i}` }));
  }
  await db.batch(queries);
}
```

<ReadMore>

查看 [Drizzle `db.batch()`](https://orm.drizzle.team/docs/batch-api) 文档以获取更多详细信息。

</ReadMore>

## 将更改推送到你的数据库

你可以将开发期间所做的更改推送到你的数据库。

### 推送表架构

你的表架构可能会随着项目的增长而变化。你可以在本地安全地测试配置更改，并在部署时推送到你的远程数据库。

你可以通过 CLI 使用 `astro db push --remote` 命令将本地架构更改推送到远程数据库：

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npm run astro db push --remote
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro db push --remote
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro db push --remote
  ```
  </Fragment>
</PackageManagerTabs>

此命令将验证你的本地更改是否可以在不丢失数据的情况下进行，并在必要时，建议如何安全地修改你的架构以解决冲突。

#### 推送破坏性架构更改

:::caution
__这将销毁你的数据库__。仅在你不需要生产数据时执行此命令。
:::

如果必须以与现有数据不兼容的方式更改表架构，则需要重置生产数据库。

要推送包含破坏性更改的表架构更新，请添加 `--force-reset` 标志以重置所有生产数据：

<PackageManagerTabs>
  <Fragment slot="npm">
  ```sh
  npm run astro db push --remote --force-reset
  ```
  </Fragment>
  <Fragment slot="pnpm">
  ```sh
  pnpm astro db push --remote --force-reset
  ```
  </Fragment>
  <Fragment slot="yarn">
  ```sh
  yarn astro db push --remote --force-reset
  ```
  </Fragment>
</PackageManagerTabs>

### 重命名表

在将架构推送到远程数据库后，可以重命名表。

如果 **没有重要的生产数据**，则可以使用 `--force-reset` 标志 [重置你的数据库](#推送破坏性架构更改)。此标志将删除数据库中的所有表并创建新的表，以匹配当前的架构。

为了在保留你的生产数据的同时重命名一个表，你必须执行一系列非破坏性更改，以安全地将本地架构推送到远程数据库。

以下示例将表从 `Comment` 重命名为 `Feedback`：

<Steps>

1. 在你的数据库配置文件中，为你想要重命名的表添加 `deprecated: true` 属性：

    ```ts title="db/config.ts" ins={2}
    const Comment = defineTable({
      deprecated: true,
    	columns: {
    		author: column.text(),
    		body: column.text(),
  		}
    });
    ```

2. 添加一个新的表架构（完全匹配现有表的属性）并使用新名称：

	  ```ts title="db/config.ts" ins={8-14}
    const Comment = defineTable({
        deprecated: true,
    	columns: {
    		author: column.text(),
    		body: column.text(),
  		}
    });
	  const Feedback = defineTable({
        columns: {
          author: column.text(),
          body: column.text(),
        }
    });
    ```

3. 使用 `astro db push --remote`[将架构推送到远程数据库](#推送表架构) 。这将添加新表并将旧表标记为已弃用。
4. 更新你的本地项目代码以使用新表而不是旧表。你可能还需要将数据迁移到新表。
5. 一旦你确信旧表在你的项目中不再使用，你可以从 `config.ts` 中删除旧表的架构：
		```ts title="db/config.ts" del={1-7}
    const Comment = defineTable({
          deprecated: true,
    	  columns: {
    		  author: column.text(),
    		  body: column.text(),
  		  }
    });

	  const Feedback = defineTable({
          columns: {
            author: column.text(),
            body: column.text(),
          }
    });
    ```
6. 再次使用 `astro db push --remote`推送到远程数据库。旧表将被删除，只留下新的、重命名的表。
</Steps>

### 推送表数据

你可能需要将数据推送到远程数据库以进行填充或数据迁移。你可以编写一个 `.ts` 文件并使用 `astro:db` 模块来编写类型安全的查询。然后，使用命令 `astro db execute <file-path> --remote` 对远程数据库执行该文件：

以下评论可以使用命令 `astro db execute db/seed.ts --remote` 进行填充：

```ts
// db/seed.ts
import { Comment } from 'astro:db';

export default async function () {
  await db.insert(Comment).values([
    { authorId: 1, body: 'Hope you like Astro DB!' },
    { authorId: 2, body: 'Enjoy!' },
  ])
}
```

<ReadMore>

查看 [CLI 参考](/zh-cn/guides/integrations-guide/db/#astro-db-cli-参考) 以获取完整的命令列表。

</ReadMore>

## 构建 Astro DB 集成

[Astro 集成](/zh-cn/reference/integrations-reference/) 可以通过额外的 Astro DB 表和填充数据来扩展用户项目。

在 `astro:db:setup` 钩子中使用 `extendDb()` 方法注册额外的 Astro DB 配置和填充文件。
`defineDbIntegration()` 辅助函数为 `astro:db:setup` 钩子提供 TypeScript 支持和自动补全。

```js {8-13}
// my-integration/index.ts
import { defineDbIntegration } from '@astrojs/db/utils';

export default function MyIntegration() {
  return defineDbIntegration({
    name: 'my-astro-db-powered-integration',
    hooks: {
      'astro:db:setup': ({ extendDb }) => {
        extendDb({
          configEntrypoint: '@astronaut/my-package/config',
          seedEntrypoint: '@astronaut/my-package/seed',
        });
      },
      // 其他集成钩子...
    },
  });
}
```

集成的 [配置](#定义你的数据库) 和 [填充](#为你的开发数据库填充数据) 文件遵循与其用户定义的等效项相同的格式。

### 在集成中进行类型安全操作

在进行集成工作时，你可能无法从 `astro:db` 导出的 Astro 生成的表类型中获益。
为了完全的类型安全，使用 `asDrizzleTable()` 辅助工具创建一个可以用于数据库操作的表引用对象。

例如，给定一个集成设置以下 `Pets` 数据库表：

```js
// my-integration/config.ts
import { defineDb, defineTable, column } from 'astro:db';

export const Pets = defineTable({
  columns: {
    name: column.text(),
    species: column.text(),
  },
});

export default defineDb({ tables: { Pets } });
```

填充文件可以导入 `Pets` 并使用 `asDrizzleTable()` 向你的表插入具有类型检查的行：

```js {2,7} /typeSafePets(?! )/
// my-integration/seed.ts
import { asDrizzleTable } from '@astrojs/db/utils';
import { db } from 'astro:db';
import { Pets } from './config';

export default async function() {
  const typeSafePets = asDrizzleTable('Pets', Pets);

  await db.insert(typeSafePets).values([
    { name: 'Palomita', species: 'cat' },
    { name: 'Pan', species: 'dog' },
  ]);
}
```

`asDrizzleTable('Pets', Pets)` 返回的值等同于 `import { Pets } from 'astro:db'`，但即使 Astro 的类型生成无法运行时也可用。
你可以在任何需要查询或插入数据库的集成代码中使用它。


## 从 Astro Studio 迁移到 Turso

<Steps>

1. 在 [Studio 仪表板](https://studio.astro.build/) 中，导航到你要迁移的项目。在设置选项卡中，使用 “Export Database（导出数据库）” 按钮下载数据库的转储。
2. 按照官方说明 [安装 Turso CLI](https://docs.turso.tech/cli/installation) 并 [注册或登录](https://docs.turso.tech/cli/authentication) 你的 Turso 帐户。
3. 使用 `turso db create` 命令在 Turso 上创建一个新数据库。
   ```sh
   turso db create [database-name]
   ```
4. 使用 Turso CLI 获取数据库 URL，并将其配置为环境变量 `ASTRO_DB_REMOTE_URL`。
   ```sh
   turso db show [database-name]
   ```
   ```dotenv
   ASTRO_DB_REMOTE_URL=[your-database-url]
   ```
5. 创建一个令牌来访问你的数据库，并将其配置为环境变量 `ASTRO_DB_APP_TOKEN`。
   ```sh
   turso db tokens create [database-name]
   ```
   ```dotenv
   ASTRO_DB_APP_TOKEN=[your-app-token]
   ```
6. 将你的 DB 架构和元数据推送到新的 Turso 数据库。
   ```sh
   astro db push --remote
   ```
7. 将步骤 1 中的数据库转储导入到新的 Turso DB 中。
   ```sh
   turso db shell [database-name] < ./path/to/dump.sql
   ```
8. 确认你的项目连接到新数据库后，你就可以安全地从 Astro Studio 中删除该项目了。

</Steps>
